# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.1496.1.6 -> 1.1496.1.7
#	   arch/ia64/Kconfig	1.38.1.10 -> 1.38.1.11
#	arch/ia64/lib/Makefile	1.22    -> 1.23   
#	               (new)	        -> 1.1     arch/ia64/lib/dec_and_lock.c
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/12/10	davidm@tiger.hpl.hp.com	1.1499
# Merge tiger.hpl.hp.com:/data1/bk/lia64/to-linus-2.5
# into tiger.hpl.hp.com:/data1/bk/lia64/linux-ia64-2.5
# --------------------------------------------
# 03/12/11	davidm@tiger.hpl.hp.com	1.1496.1.7
# ia64: Based on patch by Jerome Marchand: Add ia64-optimized
# 	atomic_dec_and_lock().  Actually, this could be the generic
# 	version for any platform that has cmpxchg().
# --------------------------------------------
#
diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig
--- a/arch/ia64/Kconfig	Sun Dec 14 00:40:13 2003
+++ b/arch/ia64/Kconfig	Sun Dec 14 00:40:13 2003
@@ -375,6 +375,11 @@
 	depends on IA32_SUPPORT
 	default y
 
+config HAVE_DEC_LOCK
+	bool
+	depends on (SMP || PREEMPT)
+	default y
+
 config PERFMON
 	bool "Performance monitor support"
 	help
diff -Nru a/arch/ia64/lib/Makefile b/arch/ia64/lib/Makefile
--- a/arch/ia64/lib/Makefile	Sun Dec 14 00:40:13 2003
+++ b/arch/ia64/lib/Makefile	Sun Dec 14 00:40:13 2003
@@ -13,6 +13,7 @@
 lib-$(CONFIG_MCKINLEY)	+= copy_page_mck.o memcpy_mck.o
 lib-$(CONFIG_PERFMON)	+= carta_random.o
 lib-$(CONFIG_MD_RAID5)	+= xor.o
+lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
 
 AFLAGS___divdi3.o	=
 AFLAGS___udivdi3.o	= -DUNSIGNED
diff -Nru a/arch/ia64/lib/dec_and_lock.c b/arch/ia64/lib/dec_and_lock.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/lib/dec_and_lock.c	Sun Dec 14 00:40:13 2003
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2003 Jerome Marchand, Bull S.A.
+ *	Cleaned up by David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * This file is released under the GPLv2, or at your option any later version.
+ *
+ * ia64 version of "atomic_dec_and_lock()" using the atomic "cmpxchg" instruction.  This
+ * code is an adaptation of the x86 version of "atomic_dec_and_lock()".
+ */
+
+#include <linux/compiler.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <asm/atomic.h>
+
+/*
+ * Decrement REFCOUNT and if the count reaches zero, acquire the spinlock.  Both of these
+ * operations have to be done atomically, so that the count doesn't drop to zero without
+ * acquiring the spinlock first.
+ */
+int
+atomic_dec_and_lock (atomic_t *refcount, spinlock_t *lock)
+{
+	int old, new;
+
+	do {
+		old = atomic_read(refcount);
+		new = old - 1;
+
+		if (unlikely (old == 1)) {
+			/* oops, we may be decrementing to zero, do it the slow way... */
+			spin_lock(lock);
+			if (atomic_dec_and_test(refcount))
+				return 1;
+			spin_unlock(lock);
+			return 0;
+		}
+	} while (cmpxchg(&refcount->counter, old, new) != old);
+	return 0;
+}
+
+EXPORT_SYMBOL(atomic_dec_and_lock);